package com.hfengxiang.example.canvasrotatedemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class MatrixView extends View implements RotateProcessor.OnRotateListener {

    private Matrix mMatrix;
    private Paint paint;
    private Bitmap bitmap;
    private float currentScale;
    private RotateProcessor rotateProcessor;
    private float lastTotal;
    private float imageW;

    public MatrixView(Context context) {
        this(context, null);
    }

    public MatrixView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public MatrixView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, -1);
    }

    public MatrixView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        bitmap = Utils.getPhoto(getResources(), getResources().getDisplayMetrics().widthPixels);
        mMatrix = new Matrix();
        rotateProcessor = new RotateProcessor();
        rotateProcessor.setRotateListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth() / 2f, getHeight() / 2f);
        canvas.drawBitmap(bitmap, mMatrix, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                rotateProcessor.handleActionDown(event);
                break;
            case MotionEvent.ACTION_MOVE:
                rotateProcessor.handleActionMove(event);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                rotateProcessor.handleActionUp(event);
                break;
        }
        return true;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        currentScale = ScaleCalculator.calculateScale(getWidth(), getHeight(), bitmap.getWidth(), bitmap.getHeight(), 0);
        mMatrix.postTranslate(-bitmap.getWidth() / 2f, -bitmap.getHeight() / 2f);
        mMatrix.postScale(currentScale, currentScale);
    }

    @Override
    public void onRotate(RotateInfo info) {
        float totalDegree = info.getTotalDegree();
        Log.i("Trace", "onRotate:" + (totalDegree - lastTotal) + "°");
        Log.i("Trace", "onRotate:" + totalDegree + "-" + lastTotal + "=" + (totalDegree - lastTotal) + "°");
        mMatrix.postRotate(totalDegree - lastTotal, info.getRotateCenter().x - getWidth() / 2f, info.getRotateCenter().y - getHeight() / 2f);
        lastTotal = totalDegree;
        invalidate();
    }

    @Override
    public void onRotateStart(RotateInfo rotateInfo) {
        Log.i("Rect", mMatrix.toShortString());
        Log.v("Trace", "start:" + rotateInfo.getTotalDegree() + "度");
    }

    @Override
    public void onRecoverStart(RotateInfo info) {

    }

    @Override
    public void onRotateEnd(RotateInfo rotateInfo) {
        Log.w("Trace", "end:" + rotateInfo.getTotalDegree() + "度");
        mMatrix.reset();
        float totalDegree = rotateInfo.getTotalDegree();
        int target = (int) (totalDegree % 360);
        if (target < 0) {
            target = 360 + target;
        }
        currentScale = ScaleCalculator.calculateScale(getWidth(), getHeight(), bitmap.getWidth(), bitmap.getHeight(), target);
//        switch (target){
//            case 0:
//            case 180:
//                mMatrix.postTranslate(-bitmap.getWidth()/2f,-bitmap.getHeight()/2f);
//                break;
//            case 90:
//            case 270:
//                mMatrix.postTranslate(-bitmap.getWidth()/2f,-bitmap.getHeight()/2f);
//                break;
//        }
        mMatrix.postTranslate(-bitmap.getWidth() / 2f, -bitmap.getHeight() / 2f);
        mMatrix.postRotate(target);
        mMatrix.postScale(currentScale, currentScale);
        Log.i("TARGET", "target=" + target);
        lastTotal = rotateInfo.getTotalDegree();
        invalidate();
    }

    @Override
    public float[] onCalculateScale(float targetDegree) {
        targetDegree = computeTargetDegree(targetDegree);
        float targetScale = ScaleCalculator.calculateScale(getWidth(), getHeight(), bitmap.getWidth(), bitmap.getHeight(), (int) targetDegree);
//        Log.i("onCalculateScale", "targetScale=" + targetScale);
        return new float[]{currentScale, targetScale};
    }

    /**
     * 根据旋转的角度计算出图片复位应当到达的角度
     *
     * @param degree 旋转的角度
     * @return 目标角度
     */
    private int computeTargetDegree(double degree) {
        int[] degrees = {0, 90, 90, 180, 180, 270, 270, 360};
        degree = degree % 360;
        int index = (int) (degree / 45);
        if (index > 0) {
            return degrees[index];
        } else {
            return -1 * degrees[-1 * index];
        }
    }
}
